#include "lexer.h"
#include "parser.h"
#include "codegen.h"
#include <iostream>
#include <fstream>
#include <string>

void printUsage(const char* programName) {
    std::cout << "Usage: " << programName << " <input_file> [output_file]\n";
    std::cout << "  input_file:  C source file to compile\n";
    std::cout << "  output_file: Assembly output file (optional, defaults to input.s)\n";
}

int main(int argc, char* argv[]) {
    if (argc < 2) {
        printUsage(argv[0]);
        return 1;
    }
    
    std::string inputFile = argv[1];
    std::string outputFile = (argc > 2) ? argv[2] : "output.s";
    
    // Read input file
    std::ifstream file(inputFile);
    if (!file.is_open()) {
        std::cerr << "Error: Could not open file " << inputFile << std::endl;
        return 1;
    }
    
    std::string source((std::istreambuf_iterator<char>(file)),
                       std::istreambuf_iterator<char>());
    file.close();
    
    try {
        // Lexical analysis
        std::cout << "Lexical analysis..." << std::endl;
        Lexer lexer(source);
        auto tokens = lexer.tokenize();
        
        std::cout << "Found " << tokens.size() << " tokens" << std::endl;
        
        // Parsing
        std::cout << "Parsing..." << std::endl;
        Parser parser(tokens);
        auto ast = parser.parse();
        
        std::cout << "AST generated successfully" << std::endl;
        std::cout << "AST:\n" << ast->toString() << std::endl;
        
        // Code generation
        std::cout << "Generating assembly..." << std::endl;
        CodeGenerator codegen;
        std::string assembly = codegen.generate(ast.get());
        
        // Write output file
        std::ofstream outFile(outputFile);
        if (!outFile.is_open()) {
            std::cerr << "Error: Could not create output file " << outputFile << std::endl;
            return 1;
        }
        
        outFile << assembly;
        outFile.close();
        
        std::cout << "Compilation successful! Output written to " << outputFile << std::endl;
        
    } catch (const std::exception& e) {
        std::cerr << "Compilation error: " << e.what() << std::endl;
        return 1;
    }
    
    return 0;
}
